package com.hncboy.chatgpt.front.controller;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.hncboy.chatgpt.base.util.WebUtil;
import com.hncboy.chatgpt.front.api.config.PayConstants;
import com.hncboy.chatgpt.front.api.utli.QRCodeGeneratorUtil;
import com.hncboy.chatgpt.front.api.log.LogFile;
import com.itextpdf.text.pdf.qrcode.WriterException;
import io.swagger.v3.oas.models.security.SecurityScheme;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;


/**
 * 当面付-扫码支付
 */
@Controller
@RequestMapping("/key")
public class AlipayScanCodeController {


    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    /**
     * alipay.trade.precreate(统一收单线下交易预创建)
     * 收银员通过收银台或商户后台调用支付宝接口，生成二维码后，展示给用户，由用户扫描二维码完成订单支付。
     */
    @RequestMapping("/preCreateScanCodeTrade")
    public void preCreateScanCodeTrade(HttpServletRequest servletRequest, HttpServletResponse servletResponse, int total_amount) throws AlipayApiException, IOException, WriterException, WriterException, com.google.zxing.WriterException {
        // 取用户Token
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        System.out.println("当前登录用户： " + tokenInfo.getLoginId());
        //=================== 1、获取alipay客户端
        AlipayClient alipayClient = getAlipayClient();

        //=================== 2、创建订单请求参数
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        request.setNotifyUrl(PayConstants.NOTIFY_URL);
        JSONObject bizContent = new JSONObject();
        String outTradeNo = getTradeNo();
//        LogFile.logResult("preCreateScanCodeTrade outTradeNo = " + outTradeNo);
        bizContent.put("out_trade_no", outTradeNo);
        //bizContent.put("out_trade_no", "20210817010101003");
        bizContent.put("total_amount", total_amount);
        bizContent.put("subject", "AIChatter");
        request.setBizContent(bizContent.toString());

        //=================== 3、响应内容
        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            System.out.println("扫码成功");
            // 保存用户ID 和 订单号
            String userId = (String) tokenInfo.getLoginId();
            String key = outTradeNo;
            String value = userId;
            stringRedisTemplate.opsForValue().set(key, value);
        } else {
            System.out.println("可能扫码失败，或者超时");
        }
        //响应为json格式，输出到浏览器看看
        servletResponse.setContentType("application/json;charset=" + PayConstants.CHARSET);
        servletResponse.getWriter().write(response.getBody());
        servletResponse.getWriter().flush();
        servletResponse.getWriter().close();
    }


    /**
     * alipay.trade.cancel(统一收单交易撤销接口)
     * 支付交易返回失败或支付系统超时，调用该接口撤销交易。
     * 如果此订单用户支付失败，支付宝系统会将此订单关闭；如果用户支付成功，支付宝系统会将此订单资金退还给用户。
     * 注意：只有发生支付系统超时或者支付结果未知时可调用撤销，其他正常支付的单如需实现相同功能只能调用申请退款API。
     * 提交支付交易后调用【查询订单API】，没有明确的支付结果再调用【撤销订单API】。
     */
    @RequestMapping("/cancelTrade")
    public void cancelTrade(HttpServletRequest servletRequest, HttpServletResponse servletResponse, @RequestParam("outTradeNo") String outTradeNo) throws AlipayApiException, IOException {

        //=================== 1、获取alipay客户端
        AlipayClient alipayClient = getAlipayClient();

        //=================== 3、请求参数
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", outTradeNo);
        //bizContent.put("out_trade_no", "20150320010101001");
        request.setBizContent(bizContent.toString());

        //=================== 3、响应内容
        AlipayTradeCancelResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            System.out.println("调用成功");
//            // 更新 usageCount 字段的值
//            ((ObjectNode) jsonNode).put("usageCount", usageCount + 2);
//
//            // 将更新后的 JSON 对象重新写回 Redis 中
//            stringRedisTemplate.opsForValue().set(value, jsonNode.toPrettyString());
        } else {
            System.out.println("调用失败");
        }
        //响应为json格式，输出到浏览器看看
        servletResponse.setContentType("application/json;charset=" + PayConstants.CHARSET);
        servletResponse.getWriter().write(response.getBody());
        servletResponse.getWriter().flush();
        servletResponse.getWriter().close();
    }

    //alipay客户端配置（重要，必须保证正确）
    private AlipayClient getAlipayClient() throws AlipayApiException {
        AlipayConfig alipayConfig = new AlipayConfig();
        //支付网关, 默认是正式环境：https://openapi.alipay.com/gateway.do，此处使用沙箱环境测试
        alipayConfig.setServerUrl(PayConstants.GATEWAY_URL);
        //商户appid
        alipayConfig.setAppId(PayConstants.APP_ID);
        //私钥 pkcs8格式的
        alipayConfig.setPrivateKey(PayConstants.RSA_PRIVATE_KEY);
        //返回格式
        alipayConfig.setFormat(PayConstants.FORMAT);
        //编码
        alipayConfig.setCharset(PayConstants.CHARSET);
        //支付宝公钥，而不是应用公钥
        alipayConfig.setAlipayPublicKey(PayConstants.ALIPAY_PUBLIC_KEY);
        //RSA2
        alipayConfig.setSignType(PayConstants.SIGN_TYPE);
        return new DefaultAlipayClient(alipayConfig);
    }

    //生成交易订单号
    private String getTradeNo() {
        //时间（精确到毫秒）
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        String localDate = LocalDateTime.now().format(ofPattern);
        //随机数
        //String randomNumeric = RandomStringUtils.randomNumeric(8);
        //return localDate + randomNumeric;
        return localDate;
    }
}
